#ifndef _X_LOG_H
#define _X_LOG_H
#include <iostream>
#include <vector>
#include <memory>
#include <sys/syscall.h>
#include <stdarg.h>
#include <string.h>
#include "xLogUtil.h"
#include "xLogOutput.h"
using namespace std;
//support single thread write log

#define XLOG_DEBUG(fmt, args...) \
                     XLOG_SYSTEM_FUNC(XLog::XLogLevel::XLOG_LEVEL_DEBUG,fmt, ##args)

#define XLOG_INFO(fmt, args...) \
                     XLOG_SYSTEM_FUNC(XLog::XLogLevel::XLOG_LEVEL_INFO,fmt, ##args)

#define XLOG_SYSTEM(fmt, args...) \
                     XLOG_SYSTEM_FUNC(XLog::XLogLevel::XLOG_LEVEL_SYSTEM,fmt, ##args)

#define XLOG_WARN(fmt, args...) \
                     XLOG_SYSTEM_FUNC(XLog::XLogLevel::XLOG_LEVEL_WARN,fmt, ##args)

#define XLOG_ERROR(fmt, args...) \
                     XLOG_SYSTEM_FUNC(XLog::XLogLevel::XLOG_LEVEL_ERROR,fmt, ##args)

#define XLOG_RAW(fmt, args...) \
                     XLOG_SYSTEM_RAW_OUT(XLog::XLogLevel::XLOG_LEVEL_ERROR,fmt, ##args)

#define XLOG_CREATE_EVENT(level,fmt,args...)  \
                     XLog::XLogEvent event(__FILE__,__LINE__,__FUNCTION__,\
                                            level,\
                                            XLog::XLogUtil::GetThreadID(),\
                                            XLog::XLogUtil::XLOG_VA_LIST_STR(fmt, ##args));

#define XLOG_SYSTEM_FUNC(level,fmt,args...) \
                     {\
                        XLOG_CREATE_EVENT(level,fmt, ##args) \
                        XLog::XLogFormat format("%t %l %d %f %m %n %c");\
                        XLog::XLogger::getInstance()->out(&event,&format);\
                     }

#define XLOG_SYSTEM_RAW_OUT(level,fmt,args...) \
                     {\
                        XLOG_CREATE_EVENT(level,fmt, ##args) \
                        XLog::XLogFormat format("%c");\
                        XLog::XLogger::getInstance()->out(&event,&format);\
                     }
namespace XLog
{
class XLogger
{
public:
    static XLogger* getInstance()
    {
        static XLogger log;
        return &log;
    }
public:
    void addXLogOutput(XLogOutputLocationBase* output);
    //void out(const XLogEvent* event);
    void out(const XLogEvent* event,XLogFormat* format);
private:
    XLogger():
    level(XLogLevel::XLOG_LEVEL_DEBUG)
    {  
        //default create file and Console Output
        XLogOutputLocationBase* console = new XLogOutputConsole();
        vecOutLocat.push_back(console);

        //XLogOutputLocationBase* file = new XLogOutputFile("xlog.log");
        //vecOutLocat.push_back(file);

    }
    ~XLogger()
    {
        for(int i=0;i<vecOutLocat.size();i++)
        {
            if(vecOutLocat[i])
            {
                delete vecOutLocat[i];
                vecOutLocat[i] = nullptr;
            }
        }
    }
    typedef std::vector<XLogOutputLocationBase*> XLogOutLocatContainer;
    XLogOutLocatContainer vecOutLocat;
    XLogLevel::Level level;
};  
}

#endif